//
// new class 2004-07-05
//
package com.hd123.rumba.util;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.StringTokenizer;

import org.apache.regexp.RE;
import org.apache.regexp.RESyntaxException;

/**
 * @author caili
 * 
 * To change this generated comment edit the template variable "typecomment":
 * Window>Preferences>Java>Templates. To enable and disable the creation of type
 * comments go to Window>Preferences>Java>Code Generation.
 */
public class InputValidator {

  /*
   *  
   */
  public static InputValidation nomalize(String s, String rule) {
    InputValidation result = null;
    if (rule == null || rule.trim().length() == 0) {
      result = new InputValidation(true, s, s, s);
    } else if (rule.startsWith("Integer") || rule.startsWith("PZInteger")) {
      result = verifyInteger(s);
      if (result.isValid() && rule.startsWith("PZInteger")) {
        Integer i = (Integer) result.getTheObject();
        if (i.intValue() < 0)
          result.setIsValid(false);
      }
    } else if (rule.startsWith("Decimal") || rule.startsWith("PZDecimal")) {
      int fractionDigits = 0;
      int idx = rule.indexOf("(");
      if (idx > 0) {
        String strFractionDigits = rule.substring(idx + 1, rule.length() - 1);
        fractionDigits = Integer.parseInt(strFractionDigits);
      }
      result = verifyDecimal(fractionDigits, s);
      if (result.isValid() && rule.startsWith("PZDecimal")) {
        BigDecimal decimal = (BigDecimal)result.getTheObject();
        if (decimal.compareTo(BigDecimal.ZERO) < 0)
          result.setIsValid(false);
      }
    } else if (rule.startsWith("Date")) {
      String datePatterns = "yyyy-MM-dd";
      int idx = rule.indexOf("(");
      if (idx > 0) {
        datePatterns = rule.substring(idx + 1, rule.length() - 1);
      }
      result = verifyDate(datePatterns, s);
    } else if (rule.startsWith("IDNumber")) {
      result = verifyIDNumber(s);
    } else {
      try {
        RE regexp = new RE(rule);
        result = new InputValidation(regexp.match(s), s, s, s);
      } catch (RESyntaxException resyntaxexception) {
        result = new InputValidation(false, s, s, s);
      }
    }
    return result;
  }

  public static InputValidation verifyIDNumber(String s) {
    InputValidation result = new InputValidation(false, s, s, s);
    if (s != null) {
      s = s.trim();
      if (s.length() == 15 || s.length() == 18) {
        InputValidation iv;
        if (s.length() == 15)
          iv = verifyDate("yyMMdd", s.substring(6, 12));
        else
          iv = verifyDate("yyyyMMdd", s.substring(6, 14));
        if (iv.isValid()) {
          result.setIsValid(true);
          result.setNomalizedValue(s);
          result.setTheObject(s);
        }
      }
    }
    return result;
  }

  public static InputValidation verifyInteger(String s) {
    InputValidation result = new InputValidation(false, s, s, s);
    String[] inputPattern = {
        "#,##0", " #,##0" };
    //		String[] outputPattern = { "0", " 0" };
    String[] outputPattern = {
        "0", "0" };
    DecimalFormat decimalFormat = new DecimalFormat();
    ParsePosition parsePosition = new ParsePosition(0);
    Number number;
    for (int i = 0; i < inputPattern.length; ++i) {
      decimalFormat.applyPattern(inputPattern[i]);
      parsePosition.setIndex(0);
      number = decimalFormat.parse(s, parsePosition);
      if (parsePosition.getIndex() != s.length())
        continue;
      if (s.indexOf(".") >= 0)
        continue;
      decimalFormat.applyPattern(outputPattern[number.doubleValue() >= 0 ? 0 : 1]);
      result.setIsValid(true);
      result.setNomalizedValue(decimalFormat.format(number));
      result.setTheObject(new Integer(number.intValue()));
      break;
    }
    // System.out.print("input = " + s + "\touput = " + result + "\t");
    return result;
  }

  public static InputValidation verifyDecimal(int fractionDigits, String s) {
    InputValidation result = new InputValidation(false, s, s, s);
    String[] inputPattern = {
        "#,##0", " #,##0" };
    String[] outputPattern = {
        "0", "0" };
    if (fractionDigits > 0) {
      char[] cs = new char[fractionDigits];
      for (int i = 0; i < fractionDigits; ++i)
        cs[i] = '0';
      String suffix = new String(cs);
      for (int i = 0; i < outputPattern.length; ++i)
        outputPattern[i] = outputPattern[i] + "." + suffix;
    }

    DecimalFormat decimalFormat = new DecimalFormat();
    ParsePosition parsePosition = new ParsePosition(0);
    Number number;
    for (int i = 0; i < inputPattern.length; ++i) {
      decimalFormat.applyPattern(inputPattern[i]);
      parsePosition.setIndex(0);
      number = decimalFormat.parse(s, parsePosition);
      if (parsePosition.getIndex() != s.length())
        continue;
      BigDecimal bigDecimal = new BigDecimal(number.doubleValue());
      bigDecimal = bigDecimal.setScale(fractionDigits, BigDecimal.ROUND_HALF_UP);
      decimalFormat.applyPattern(outputPattern[number.doubleValue() >= 0 ? 0 : 1]);
      result.setIsValid(true);
      result.setNomalizedValue(decimalFormat.format(bigDecimal.doubleValue()));
      result.setTheObject(bigDecimal);
      break;
    }
    // System.out.print("input = " + s + "\touput = " + result + "\t");
    return result;
  }

  public static InputValidation verifyDate(String patterns, String s) {
    s = s.replaceAll("&nbsp;", " ");
    InputValidation result = new InputValidation(false, s, s, s);
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
    simpleDateFormat.setLenient(false);
    StringTokenizer st = new StringTokenizer(patterns, ";", false);
    String inputPattern, outputPattern = "yyyy-MM-dd HH:mm:ss";
    boolean isFirstPattern = true;
    while (st.hasMoreTokens()) {
      inputPattern = st.nextToken();
      if (isFirstPattern) {
        outputPattern = inputPattern;
        isFirstPattern = false;
      }
      try {
        simpleDateFormat.applyPattern(inputPattern);
        Date date = simpleDateFormat.parse(s);
        simpleDateFormat.applyPattern(outputPattern);
        String r = simpleDateFormat.format(date);
        if (inputPattern.startsWith("yyyy")) {
          if ((s.length() >= 4) && r.substring(0, 4).equals(s.substring(0, 4))) {
            result.setIsValid(true);
            result.setNomalizedValue(r);
            result.setTheObject(date);
            break;
          }
        } else {
          result.setIsValid(true);
          result.setNomalizedValue(r);
          result.setTheObject(date);
          break;
        }
      } catch (ParseException e) {
        // nothing
      }
    }
    // System.out.print("input = " + s + "\touput = " + result + "\t");
    return result;
  }

}
